home *** CD-ROM | disk | FTP | other *** search
/ WINMX Assorted Textfiles / Ebooks.tar / Text - Tech - Hardware - How To Use a Magnetic Card Reader with Source Code (TXT).zip / (ebook - hack) - Magnetic Swipe Card Reader.txt
Text File  |  2003-11-01  |  18KB  |  1,051 lines

  1.  
  2.  
  3. Summary of replies to the following request:
  4.  
  5.  
  6.  
  7. Subject: Mag Card Swipe Reader: Need Help!
  8.  
  9.  
  10.  
  11. Hello, Everybody.
  12.  
  13.  
  14.  
  15. I just picked up one of those swipe readers for mag stripes on credit
  16.  
  17. cards etc. from a surplus outfit (American Science & Surplus in
  18.  
  19. Evanston, IL  708/475-8440 for those who are interested). It's not the
  20.  
  21. complete unit with keypad, display, etc. but rather just the guts of the
  22.  
  23. subassembly which actually reads the card (hey, what do you expect for
  24.  
  25. $2.50?? ;-) Since it's surplus and taken out of a larger piece of
  26.  
  27. equipment, I have no docs for this sucker. My hope is that someone else
  28.  
  29. picked up one of these things to play with and has some docs or has figured
  30.  
  31. out enough about it to get it to work, OR can tell me who to contact to get
  32.  
  33. more info on this beast. I figured this would be a good place to ask
  34.  
  35. since I've seen people asking about swipe card readers recently.
  36.  
  37.  
  38.  
  39. Anyway, here's a description:
  40.  
  41. The unit is about 6" long, 1" wide, and maybe 2" high. It consists of a
  42.  
  43. metal backing plate, attached to which is a black plastic guide channel
  44.  
  45. through which you swipe the card. On one side of the plastic channel is a
  46.  
  47. read head for the mag stripe; on the opposite side is a small printed circuit
  48.  
  49. board.
  50.  
  51.  
  52.  
  53. Removing the plastic guide from the mounting plate reveals that the
  54.  
  55. manufacturer is SR&D corporation of Tokyo, Japan. The model number is
  56.  
  57. MCR-175-1R-0803; a serial number is also listed. The SR&D logo-lettering
  58.  
  59. appears on the component side of the PC board, and on the foil side of
  60.  
  61. the board the SR&D is repeated along with the code "FNC -065-1" in the
  62.  
  63. upper right hand corner. The board has one IC on it (I can't easily see
  64.  
  65. what the numbers are on this chip, so I'm not sure what kind it is other
  66.  
  67. than a 16 pin DIP). There is a spot for another chip, an 8-pin DIP for
  68.  
  69. which the screened label reads "IC2 6914", but this chip and some other
  70.  
  71. resistors, capacitors, etc. are missing.
  72.  
  73.  
  74.  
  75. Finally, there are 5 wires coming from the assembly and terminating in a
  76.  
  77. small connector similar to power supply connectors for 3.5" floppy drives.
  78.  
  79. The wires are red, yellow, green, blue, and black.
  80.  
  81.  
  82.  
  83. I haven't hacked on this thing at all yet, since I don't know what its
  84.  
  85. power requirements are or even which are power leads and which are data
  86.  
  87. leads. If anyone has any information on this puppy which might help me,
  88.  
  89. I'd love to hear from you! Please email me. I'll share whatever I find
  90.  
  91. out with anyone who's interested.
  92.  
  93.  
  94.  
  95. Thanks!
  96.  
  97.  
  98.  
  99. ---
  100.  
  101.  
  102.  
  103. [Editor's Note: The following is a concatenation of the replies I received
  104.  
  105. to the net.request above. After the replies I have included information
  106.  
  107. which was posted to the net on how mag stripe cards are encoded (in case
  108.  
  109. anyone missed it). Finally, I have included some software that I threw
  110.  
  111. together to play with the card reader. This file contains all the information
  112.  
  113. I have on this subject. Additions are most welcome.
  114.  
  115.  
  116.  
  117. You'll notice I didn't get any farther than simply reading the raw signal
  118.  
  119. from the card; of the two card readers I ordered, one was completely DOA,
  120.  
  121. and the other had a faulty clock output (at least I assume that it was a
  122.  
  123. clock output; I was never able to read any sort of signal from that line).
  124.  
  125. Someone with a fully functional reader can easily extend what I wrote to get
  126.  
  127. it to decode the actual data content of the card. If you do decide to make
  128.  
  129. modifications and/or extensions, I'd appreciate a copy of whatever
  130.  
  131. changes you make (email to tmkk@uiuc.edu).  Enjoy!]
  132.  
  133.  
  134.  
  135.  
  136.  
  137. Subject: Re: Mag Card Swipe Reader: Need Help!
  138.  
  139.  
  140.  
  141. I am truly amazed that someone else is trying to use this device!  I got
  142.  
  143. mine about 2 years ago and spent some time trying to find the manufacturer.
  144.  
  145. I found a listing for SR&D in the Noth America technical directory at 
  146.  
  147. the public library.  I found the listing for the American sales office
  148.  
  149. in Los Angeles.  I tried calling but the company had gone out of 
  150.  
  151. business.  There was no listing in the local phone directory either.
  152.  
  153. I then tried calling the head office in Japan, but they also had
  154.  
  155. gone out of business.  I haven't seen the company listed in any recent
  156.  
  157. electronics directories, so I think they really are gone.
  158.  
  159.  
  160.  
  161. I have spent about an hour looking at the signals on the outputs
  162.  
  163. of the device.  One signal line is a /STATUS line which indicates
  164.  
  165. when a card is been moved through the unit.  The other 2 lines
  166.  
  167. pulse in response to a magnetic card.  I believe the IC performs
  168.  
  169. Manchester decoding and clock recovery for the read channel, so one
  170.  
  171. output line is DATA and the other is CLOCK.  
  172.  
  173.  
  174.  
  175. That is as far as I got 2 years ago and I had forgot about it until
  176.  
  177. now.  If you receive any other info, please send a copy to me!
  178.  
  179.  
  180.  
  181. ---
  182.  
  183.  
  184.  
  185. >Finally, there are 5 wires coming from the assembly and terminating in a
  186.  
  187. >small connector similar to power supply connectors for 3.5" floppy drives.
  188.  
  189. >The wires are red, yellow, green, blue, and black.
  190.  
  191.  
  192.  
  193. If its anything like the units I worked with, I think you  will find
  194.  
  195. that the five wires are:
  196.  
  197.  
  198.  
  199.         +5v
  200.  
  201.     Gnd
  202.  
  203.     Clock
  204.  
  205.     Data
  206.  
  207.     Card detected
  208.  
  209.  
  210.  
  211. But I don't know active levels, or which wire is what.
  212.  
  213.  
  214.  
  215. ---
  216.  
  217.  
  218.  
  219. I picked few week ago a magnetic credit card reader from a 
  220.  
  221. another surplus outfit. It cost about the sam es yours. 
  222.  
  223. My card reader was made by MAGTEK and was diffrent from
  224.  
  225. your reder in many ways. The reader I have has 4 ICs and
  226.  
  227. some of them are standard TTL chip, so I could easily 
  228.  
  229. quess the power requiments (5V) and power connectors.
  230.  
  231. My card reader had 6 pin connector. 
  232.  
  233. I put the power to the reader and started to examine 
  234.  
  235. the signals with multimeter and a little crystal
  236.  
  237. earphine (my favourite electronics hacking tool).
  238.  
  239. I found that output signals were something like
  240.  
  241. that: data out, data clock out, data readable and
  242.  
  243. and card ath the end of the reader.
  244.  
  245. Then I connected the reader to the joystick port
  246.  
  247. of my 386SX and made a little Turbo Pascal program
  248.  
  249. for reading the card.
  250.  
  251.  
  252.  
  253. Spare printer port is the interface I use very often to connect
  254.  
  255. diffrent hardware circuit to my computer. This time I decided
  256.  
  257. to use game port beacuse it can also provide the power to the
  258.  
  259. reader.
  260.  
  261.  
  262.  
  263. My program simply prints out the bits from the card. I have not
  264.  
  265. found the way to decode the bits to corresponding numbers. The
  266.  
  267. program so prints all 237 bits form the card to screen.
  268.  
  269. If you have any information about data coding, I an interrested
  270.  
  271. in hearing that.
  272.  
  273.  
  274.  
  275. Here is the meanings of the bytes in port $201:
  276.  
  277. D7: 0 -> card pushed to the end of the reader
  278.  
  279. D6: the read data from card
  280.  
  281. D5: 0 -> data stream readable
  282.  
  283. D4: the data clock
  284.  
  285.  
  286.  
  287. Program CardReader;
  288.  
  289.  
  290.  
  291. Uses Crt,Binary;
  292.  
  293.  
  294.  
  295. Const
  296.  
  297.    gameport=$201;
  298.  
  299.  
  300.  
  301.  
  302.  
  303. Procedure Wait_start;
  304.  
  305. Begin
  306.  
  307.    Repeat Until (Port[gameport] and 32)=0;
  308.  
  309. End;
  310.  
  311.  
  312.  
  313. Function data_readable:boolean;
  314.  
  315. Begin
  316.  
  317.    data_readable:=((Port[gameport] and 32)=0);
  318.  
  319. End;
  320.  
  321.  
  322.  
  323. Procedure Wait_clock;
  324.  
  325. Begin
  326.  
  327.    Repeat Until (Port[gameport] and 16)=0;
  328.  
  329. End;
  330.  
  331.  
  332.  
  333. Procedure Wait_clock_end;
  334.  
  335. Begin
  336.  
  337.    Repeat Until (Port[gameport] and 16)=16;
  338.  
  339. End;
  340.  
  341.  
  342.  
  343. Function data_input:byte;
  344.  
  345. Begin
  346.  
  347.    If (Port[gameport] and 64)=0 Then data_input:=0
  348.  
  349.       Else data_input:=1;
  350.  
  351. End;
  352.  
  353.  
  354.  
  355. Function card_at_end:boolean;
  356.  
  357. Begin
  358.  
  359.    card_at_end:=((Port[gameport] and 128)=0);
  360.  
  361. End;
  362.  
  363.  
  364.  
  365. Procedure test;
  366.  
  367. Begin
  368.  
  369.    Wait_start;
  370.  
  371.    Repeat
  372.  
  373.       Writeln(ByteBin(Port[$201]));
  374.  
  375.    Until keypressed;
  376.  
  377. End;
  378.  
  379.  
  380.  
  381. Begin
  382.  
  383.    ClrScr;
  384.  
  385.    Wait_start;
  386.  
  387.    While data_readable Do Begin
  388.  
  389.       Wait_clock;
  390.  
  391.       Write(data_input);
  392.  
  393.       Wait_clock_end;
  394.  
  395.    End;
  396.  
  397.    Repeat Until KeyPressed;
  398.  
  399. End.
  400.  
  401.  
  402.  
  403. ---
  404.  
  405.  
  406.  
  407. Wiring color code for the SR&D MCR-175-1R-0803 mag stripe card reader:
  408.  
  409.  
  410.  
  411.    Red:         +5V
  412.  
  413.  Black:         Gnd
  414.  
  415. Yellow:         /Card Detect
  416.  
  417.  Green:         Clock (?? - non-functional on the unit I have)
  418.  
  419.   Blue:         /Data
  420.  
  421.  
  422.  
  423.  
  424.  
  425. The leading '/' indicates an active low TTL signal.
  426.  
  427.  
  428.  
  429.  
  430.  
  431. ---
  432.  
  433.  
  434.  
  435.            Quick 'n Dirty guide to the enclosed reader software
  436.  
  437.            ----------------------------------------------------
  438.  
  439.  
  440.  
  441. Hooking the SR&D MCR-175-1R-0803 card reader to your PC:
  442.  
  443.  
  444.  
  445. The included software is written specifically for the following
  446.  
  447. configuration; if your wiring is different, you'll need to make
  448.  
  449. corresponding changes to the software. Note also that the port
  450.  
  451. address is hard-coded to look for LPT2's status port (at address
  452.  
  453. 0x279). If you're using a different port address, be sure to change the
  454.  
  455. port address value.
  456.  
  457.  
  458.  
  459. SR&D Wire       Printer Port Pin        Port Bit        Signal
  460.  
  461. ---------       ----------------        --------        ------
  462.  
  463. Yellow          11                      7               /CARD DETECT
  464.  
  465. Blue            10                      6               /DATA
  466.  
  467. Black           18                      N/A             (Ground)
  468.  
  469.  
  470.  
  471. Power to the reader was provided by a separate power supply, basically
  472.  
  473. one of those black plastic DC power packs fed through a 7805 regulator
  474.  
  475. chip.
  476.  
  477.  
  478.  
  479.  
  480.  
  481. Compiling the software:
  482.  
  483.  
  484.  
  485. Compile SWIPE.C (using SMALL memory model), assemble SWIPEISR.ASM, and
  486.  
  487. link the two together.
  488.  
  489.  
  490.  
  491.  
  492.  
  493. Using the software:
  494.  
  495.  
  496.  
  497. To use SWIPE.EXE, simply hook the reader up to your LPT2: port, power it
  498.  
  499. up, then run SWIPE. When you're ready, press the ENTER key, and swipe a
  500.  
  501. card through the reader. The program will read the data from the card and
  502.  
  503. store it in a buffer (but will not decode the data; that is left as an
  504.  
  505. excercise ;-). After the card has been read, press ENTER again and the
  506.  
  507. contents of the buffer will be dumped to stdout. To save the card data to
  508.  
  509. a file, simply redirect SWIPE's output on the command line, e.g.
  510.  
  511.  
  512.  
  513. SWIPE > citibank.out
  514.  
  515.  
  516.  
  517. Please let me know of any changes, bug fixes, or improvements you make to
  518.  
  519. this code. Send email to tmkk@uiuc.edu.
  520.  
  521.  
  522.  
  523. Thanks, and have fun!
  524.  
  525.  
  526.  
  527. --- CUT HERE ---
  528.  
  529.  
  530.  
  531. /*
  532.  
  533.  * S W I P E . C
  534.  
  535.  *
  536.  
  537.  * Written:
  538.  
  539.  *     1/11/92
  540.  
  541.  *
  542.  
  543.  * Description: Quick 'n Dirty reader program for SR&D mag stripe card reader.
  544.  
  545.  *     Reads data from the input port as long as a card is detected in the
  546.  
  547.  *     card slot. After sampling, the data is dumped to stdout, and may
  548.  
  549.  *     be redirected to a file if desired.
  550.  
  551.  *
  552.  
  553.  * Note: Written for Borland C++ 3.0 - may require changes to compile under
  554.  
  555.  *     MSC or others. Compile in SMALL model.
  556.  
  557.  *
  558.  
  559.  */
  560.  
  561.  
  562.  
  563. #include <stdio.h>
  564.  
  565. #include <conio.h>
  566.  
  567. #include <process.h>
  568.  
  569. #include <dos.h>
  570.  
  571. #include <math.h>
  572.  
  573. #include <stdlib.h>
  574.  
  575. #include <assert.h>
  576.  
  577. #include <string.h>
  578.  
  579.  
  580.  
  581. /* timer chip programming register port addresses */
  582.  
  583. #define COMMAND_REG 0x43
  584.  
  585. #define CHANNEL0 0x40
  586.  
  587.  
  588.  
  589. /* size of sample buffer */
  590.  
  591. #define MAXSAMPLE 4096
  592.  
  593.  
  594.  
  595. typedef unsigned char byte;
  596.  
  597.  
  598.  
  599.  
  600.  
  601. /* global variables */
  602.  
  603. byte *databuf;  /* buffer for the sampled data */
  604.  
  605.  
  606.  
  607. /* interprocess communication data */
  608.  
  609. byte *bufp;         /* data buffer pointer */
  610.  
  611. unsigned nsamp;     /* number of samples to be made */
  612.  
  613. unsigned port;      /* input port address */
  614.  
  615. int enab=0;         /* flag to enable/disable sampling */
  616.  
  617. int start=0;        /* flag indicating that sampling has begun */
  618.  
  619.  
  620.  
  621. /* ISR prototype */
  622.  
  623. extern void interrupt shand(void);
  624.  
  625.  
  626.  
  627.  
  628.  
  629.  
  630.  
  631. void program_timer(int channel, unsigned count)
  632.  
  633. /*
  634.  
  635.  * P R O G R A M _ T I M E R
  636.  
  637.  *
  638.  
  639.  * Description: Programs the given count value into the specified channel of
  640.  
  641.  *     the IBM 825x timer chip. Channel 0 is the time-of-day-clock interrupt;
  642.  
  643.  *     channel 2 is the speaker pulser.
  644.  
  645.  *
  646.  
  647.  * Parameter:
  648.  
  649.  *     channel (in) - Channel to be programmed.
  650.  
  651.  *     count (in) - Count value with which to program timer chip.
  652.  
  653.  *
  654.  
  655.  */
  656.  
  657. {
  658.  
  659.  
  660.  
  661.     outportb(COMMAND_REG, 0x36);  /* set up for reprogramming */
  662.  
  663.     outportb(CHANNEL0 + channel, count & 0xff);  /* lo byte first */
  664.  
  665.     outportb(CHANNEL0 + channel, count >> 8);  /* then hi byte */
  666.  
  667. }
  668.  
  669.  
  670.  
  671. void sample_data(int count)
  672.  
  673. /*
  674.  
  675.  * S A M P L E _ D A T A
  676.  
  677.  *
  678.  
  679.  * Description: Sets up for data collection from the printer port using
  680.  
  681.  *     the SHAND interrupt service routine (see SWIPEISR.ASM). This routine
  682.  
  683.  *     reprograms the timer chip for the desired sampling rate, sets up
  684.  
  685.  *     the interprocess communication area, and starts the sampling process.
  686.  
  687.  *     The actual sampling is done in the SHAND procedure. This routine
  688.  
  689.  *     waits until sampling has been completed before returning.
  690.  
  691.  *
  692.  
  693.  */
  694.  
  695. {
  696.  
  697. void interrupt (*oldhand)(void);  /* pointer to old interrupt vector */
  698.  
  699.  
  700.  
  701.     /* save old interrupt vector */
  702.  
  703.     oldhand = getvect(0x1c);
  704.  
  705.  
  706.  
  707.     /* clear enable flag */
  708.  
  709.     enab = 0;
  710.  
  711.     start = 0;
  712.  
  713.  
  714.  
  715.     /* install new vector */
  716.  
  717.     setvect(0x1c, shand);
  718.  
  719.  
  720.  
  721.     /* set up interprocess communications area */
  722.  
  723.     nsamp = 0;
  724.  
  725.     bufp = databuf;
  726.  
  727.     port = 0x279;  /* address of printer status register */
  728.  
  729.  
  730.  
  731.     cprintf("Sampling at %fHz (= %fms)....",
  732.  
  733.        1193180.0 / (float)count, (float)count / 1193.18);
  734.  
  735.  
  736.  
  737.     /* reprogram timer chip */
  738.  
  739.     program_timer(0, count);
  740.  
  741.  
  742.  
  743.     /* enable sampling */
  744.  
  745.     enab = 1;
  746.  
  747.  
  748.  
  749.     /* wait until sampling is completed */
  750.  
  751.     while (enab) ;
  752.  
  753.  
  754.  
  755.     /* restore standard timing value */
  756.  
  757.     program_timer(0, 0);
  758.  
  759.  
  760.  
  761.     /* reinstall old handler vector */
  762.  
  763.     setvect(0x1c, oldhand);
  764.  
  765.  
  766.  
  767.     cprintf(" completed.\r\n");
  768.  
  769.  
  770.  
  771. }
  772.  
  773.  
  774.  
  775.  
  776.  
  777. void main()
  778.  
  779. {
  780.  
  781. unsigned i;
  782.  
  783.  
  784.  
  785.     /* allocate memory */
  786.  
  787.     databuf = calloc(MAXSAMPLE, sizeof(byte));
  788.  
  789.     assert (databuf != NULL);
  790.  
  791.  
  792.  
  793.     cprintf("Press <ENTER> when ready to swipe card:");
  794.  
  795.     getchar();
  796.  
  797.     sample_data(12);  /* This works out to about a 100kHz sampling rate  */
  798.  
  799.  
  800.  
  801.     cprintf("Sampling completed, %u samples total.\r\n", nsamp);
  802.  
  803.     cprintf("Press <ENTER> to dump data.\r\n\r\n");
  804.  
  805.     getchar();
  806.  
  807.  
  808.  
  809.     /* dump data to stdout */
  810.  
  811.     for (i=0; i<nsamp; ++i)
  812.  
  813.     if (kbhit())
  814.  
  815.         break;
  816.  
  817.     else
  818.  
  819.         printf("%u\n", databuf[i]);
  820.  
  821.  
  822.  
  823.     free (databuf);
  824.  
  825.  
  826.  
  827. }
  828.  
  829.  
  830.  
  831. --- CUT HERE ---
  832.  
  833.  
  834.  
  835. ;
  836.  
  837. ; S W I P E I S R . A S M
  838.  
  839. ;
  840.  
  841. ; Interrupt Service Routine to sample swipe reader.
  842.  
  843. ;
  844.  
  845.  
  846.  
  847. _TEXT   segment byte public 'CODE'
  848.  
  849. DGROUP    group    _DATA,_BSS
  850.  
  851.     assume    cs:_TEXT,ds:DGROUP,ss:DGROUP
  852.  
  853. _TEXT    ends
  854.  
  855.  
  856.  
  857. _DATA    segment word public 'DATA'
  858.  
  859. ; Nuthin' in here!
  860.  
  861. _DATA   ends
  862.  
  863.  
  864.  
  865. _BSS    segment word public 'BSS'
  866.  
  867. ; Nuthin' in here either!
  868.  
  869. _BSS    ends
  870.  
  871.  
  872.  
  873. _TEXT    segment    byte public 'CODE'
  874.  
  875. ;
  876.  
  877. ; S H A N D
  878.  
  879. ;
  880.  
  881. ; Description: Sample interrupt handler for timer extension interrupt 0x1c.
  882.  
  883. ;
  884.  
  885. ; Note: Assumes that the /CARD DETECT line appears on bit 7 of the input
  886.  
  887. ;     port. This bit corresponds to pin 11 on the standard PC printer port.
  888.  
  889. ;     Also, the PC printer port card inverts the signal on this pin; thus,
  890.  
  891. ;     bit 7 is *set* when a card is in the reader, even though /CARD DETECT
  892.  
  893. ;     is an active low signal.
  894.  
  895. ;
  896.  
  897. _shand    proc    far
  898.  
  899.     push    ax
  900.  
  901.     push    bx
  902.  
  903.     push    dx
  904.  
  905.     push    ds
  906.  
  907.     push    si
  908.  
  909.     push    di
  910.  
  911.     push    bp
  912.  
  913.     mov    bp,DGROUP
  914.  
  915.     mov    ds,bp
  916.  
  917.  
  918.  
  919.         cmp     word ptr DGROUP:_enab, 0                ; Are we turned on?
  920.  
  921.         je      ciao                                    ; Nope - goodbye!
  922.  
  923.  
  924.  
  925.         mov     dx, word ptr DGROUP:_port               ; Get port address
  926.  
  927.         cmp     word ptr DGROUP:_start, 0               ; Has sampling begun?
  928.  
  929.         jne     doit                                    ; Yup - hop to it!
  930.  
  931.  
  932.  
  933. ;
  934.  
  935. ; Sampling is enabled but has not actually begun because no card has yet been
  936.  
  937. ;     detected in the slot of the reader. Check to see if a card has arrived
  938.  
  939. ;     yet and, if it has, set the flag to indicate that sampling should begin.
  940.  
  941. ;
  942.  
  943.         in      al, dx                                  ; sample port
  944.  
  945.         test    al, 80h                                 ; card detected?
  946.  
  947.         jz      ciao                                    ; nope - later!
  948.  
  949.  
  950.  
  951.         mov     word ptr DGROUP:_start, 1               ; card's there,
  952.  
  953.                                                         ; start reading it
  954.  
  955.         jmp     saveit
  956.  
  957. ;
  958.  
  959. doit:
  960.  
  961.         in      al, dx                                  ; Read the port
  962.  
  963.         test    al, 80h                                 ; card detect bit set?
  964.  
  965.         jz      disable                                 ; if not, quit
  966.  
  967. ;
  968.  
  969. ; Data is still valid; get buffer pointer and save the data
  970.  
  971. ;
  972.  
  973. saveit:
  974.  
  975.         mov     bx,word ptr DGROUP:_bufp                ; get addr. to write
  976.  
  977.         mov     byte ptr [bx],al                        ; save sampled value
  978.  
  979.         inc     word ptr DGROUP:_bufp                   ; and bump the ptr
  980.  
  981.  
  982.  
  983.         inc     word ptr DGROUP:_nsamp                  ; update sample count
  984.  
  985.         jmp     ciao                                    ; and skeedaddle
  986.  
  987.  
  988.  
  989. disable:
  990.  
  991.         mov     word ptr DGROUP:_enab,0                 ; card no longer
  992.  
  993.                                                         ; detected - disable
  994.  
  995.                                                         ; sampling
  996.  
  997. ciao:
  998.  
  999.         pop     bp                                      ; restore context
  1000.  
  1001.     pop    di
  1002.  
  1003.     pop    si
  1004.  
  1005.     pop    ds
  1006.  
  1007.     pop    dx
  1008.  
  1009.     pop    bx
  1010.  
  1011.     pop    ax
  1012.  
  1013.     iret    
  1014.  
  1015. _shand    endp
  1016.  
  1017. _TEXT    ends
  1018.  
  1019.  
  1020.  
  1021. _DATA    segment word public 'DATA'
  1022.  
  1023. ;s@      label   byte
  1024.  
  1025. _DATA    ends
  1026.  
  1027.         extrn   _nsamp:word
  1028.  
  1029.     extrn    _port:word
  1030.  
  1031.     extrn    _bufp:word
  1032.  
  1033.     extrn    _enab:word
  1034.  
  1035.         extrn   _start:word
  1036.  
  1037. _TEXT    segment    byte public 'CODE'
  1038.  
  1039.     extrn    _inportb:near
  1040.  
  1041. _TEXT    ends
  1042.  
  1043.     public    _shand
  1044.  
  1045.     end
  1046.  
  1047.  
  1048.  
  1049. === END OF SUMMARY ===
  1050.  
  1051.